/// \file Snake.h
/// \date 2012-12-05
/// \brief Class that models the snake and its behavour

#ifndef SNAKE_MODEL_SNAKE_H_
#define SNAKE_MODEL_SNAKE_H_

#include <Model/Include/Element.h>

namespace Model
{
/// \brief Class that models the snake and its behavour
class Snake
{
    public:
        // ========== LIFECYCLE ========== //

        /// \brief Constructor
        /// \details creates a snake with its initial head position in the scene,
        /// and also the two first body elements towards DOWN direction.
        /// By default its direction is UP.        
        Snake(const int &initial_pos_x, const int &initial_pos_y);

        /// \brief Destructor
        /// \details Releases each body element (including the head)
        virtual ~Snake();

        // ========== OVERLODED OPERATORS ========== //
        
        // ========== METHODS ========== //
        /// \brief adds an element to the tail of the snake
        /// \details the new element is added in the tail of the snake
        void addElement(Element* element);

        /// \brief moves the snake according to its velocity and direction
        /// \details receives time elapsed since last movement (last call to this function)
        void move(const int &time_elapsed_ms);

        /// \brief turns the snake to the right
        void turnRight();

        /// \brief turns the snake to the left
        void turnLeft();

        /// \brief check if the snake is self-colliding
        bool checkSelfCollition() const;

        /// \brief returns the direction vector according to snake's direction
        void getDirection(int* at_x, int* at_y) const;
        
        // ========== GETTERS ========== //
        
        /// \brief get head element
        const Element* getHeadElement() const;
        
        // ========== SETTERS ========== //
        
        /// \brief set a new velocity
        void setVelocity( const int &new_velocity);
        
        // ========== INQUIRY ========== //
        
    private:
        /// \brief enum to describe the possible direction
        /// \details the order inside the enum is VERY IMPORTANT because it is used in the turn* methods.
        typedef enum
        {
            UP = 0,
            RIGHT,
            DOWN,
            LEFT,
            TOTAL_COUNT
        }SnakeDirectionType;

        // ========== INTERNAL METHODS ========== //
        void move();

        // ========== ATTRIBUTES ========== //
        /// \brief head element
        Element* head;

        /// \brief tail element
        Element* tail;

        /// \brief velocity, units per second
        int velocity;

        /// \brief direction
        SnakeDirectionType direction;

        /// \brief this is an auxiliary to not allow to turning without an advance in the head in between
        bool allow_turning;

        /// \brief time in miliseconds that passed from last movement
        int time_ms_from_last_movement;
};
};

#endif // SNAKE_MODEL_SNAKE_H_
